﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace DienLib.SummitLib
{
    /// <summary>
    /// Wrapper for UnitTextBox Summit UserControl
    /// </summary>
    public class UnitTextBox
    {
        private Control _refobj;
        private TextBox a_TextBoxEdit;
        private Label a_LabelUnit;

        //private ContextMenu a_ContextMenu1;
        //private Form a_m_frmUnitSelector;
#if DEBUG        
        private Panel a_PanelBorder;
        private Panel a_PanelTextBoxState;
        private SplitContainer a_Splitter1;
#endif
        //private bool m_flash = false;
        public UnitTextBox(Control refUnitTextBox)
        {
            InitCode(refUnitTextBox);
        }

        private bool _IsTest = false;
        /// <summary>
        /// Test Object with default Constructor
        /// </summary>
        public UnitTextBox(Control refUnitTextBox, bool test)
        {
            _IsTest = test;
            InitCode(refUnitTextBox);
        }

        private void InitCode(Control refUnitTextBox)
        {
            _refobj = refUnitTextBox;
            a_TextBoxEdit = DienLib.Reflector.GetField<TextBox>(_refobj, "_TextBoxEdit");
            a_LabelUnit = DienLib.Reflector.GetField<Label>(_refobj, "_LabelUnit");

            //a_ContextMenu1 = DienLib.Reflector.GetField<ContextMenu>(_refobj, "_LabelUnit");
            //a_m_frmUnitSelector = DienLib.Reflector.GetField<Form>(_refobj, "_LabelUnit");
#if DEBUG
            a_PanelBorder = DienLib.Reflector.GetField<Panel>(_refobj, "_PanelBorder");
            a_PanelTextBoxState = DienLib.Reflector.GetField<Panel>(_refobj, "_PanelTextBoxState");
            a_Splitter1 = DienLib.Reflector.GetField<SplitContainer>(_refobj, "_Splitter1");
#endif
            //a_TextBoxEdit.Parent.Paint += new PaintEventHandler(a_TextBoxEdit_Parent_Paint);
            // TextBox don't call OnPaint itself (& also doesn't need to repain in any case) instead just pain by container (or parent on paint).
            // Can create a wrapper inherit & use SetStyle as another way

            //a_LabelUnit.Paint += new PaintEventHandler(a_LabelUnit_Paint);
        }

       

        private string TextValue
        {
            get
            {
                if (_refobj.InvokeRequired) return (string)_refobj.Invoke((Func<string>)delegate { return DienLib.Reflector.GetProperty<string>(_refobj, "TextValue"); });
                else return DienLib.Reflector.GetProperty<string>(_refobj, "TextValue");
            }
            set
            {
                if (_refobj.InvokeRequired) _refobj.Invoke((MethodInvoker)delegate { DienLib.Reflector.SetProperty(_refobj, "TextValue", value); });
                else DienLib.Reflector.SetProperty(_refobj, "TextValue", value);
            }
        }

        public string Text
        {
            get
            {
                if (_refobj.InvokeRequired) return (string)_refobj.Invoke((Func<string>)delegate { return DienLib.Reflector.GetProperty<string>(_refobj, "Text"); });
                else return DienLib.Reflector.GetProperty<string>(_refobj, "Text");
            }
            set
            {
                Rectangle rect;
                if (a_TextBoxEdit.InvokeRequired) rect = (Rectangle)a_TextBoxEdit.Invoke((Func<Rectangle>)delegate { return a_TextBoxEdit.RectangleToScreen(a_TextBoxEdit.ClientRectangle); });
                else rect = a_TextBoxEdit.RectangleToScreen(a_TextBoxEdit.ClientRectangle);

                if (Properties.Settings.Default.UseGDIWhenDrawBorder)
                {   // Use Polyline with NOT_XOR_PEN form GDI
                    rect.X -= 4;
                    rect.Y -= 4;
                    rect.Width += 7;
                    rect.Height += 7;
                }
                else
                {   // Use ControlPaint.DrawReversibleFrame (GDI+)
                    rect.X -= 3;
                    rect.Y -= 3;
                    rect.Width += 7;
                    rect.Height += 7;
                }


                /*rect.X -= left;
                rect.Y -= top;
                rect.Width += (left + right);
                rect.Height += (top + bot);*/

                DienLib.WinAPI.BlinkBorderBefore(rect);
                if (_refobj.InvokeRequired) _refobj.Invoke((MethodInvoker)delegate { DienLib.Reflector.SetProperty(_refobj, "Text", value); });
                else DienLib.Reflector.SetProperty(_refobj, "Text", value);
                DienLib.WinAPI.BlinkBorderAfter(_refobj);
            }
        }


        public static int left, right, top, bot;
        public string Unit
        {
            get
            {
                if (_refobj.InvokeRequired) return (string)_refobj.Invoke((Func<string>)delegate { return DienLib.Reflector.GetProperty<string>(_refobj, "Unit"); });
                else return DienLib.Reflector.GetProperty<string>(_refobj, "Unit");
            }
            set
            {
                Rectangle rect;
                if (a_LabelUnit.InvokeRequired) rect = (Rectangle)a_LabelUnit.Invoke((Func<Rectangle>)delegate { return a_LabelUnit.RectangleToScreen(a_LabelUnit.ClientRectangle); });
                else rect = a_LabelUnit.RectangleToScreen(a_LabelUnit.ClientRectangle);

#if !_DebugDrawBorder_uomBHP_ExpandClientRectange
                if (Properties.Settings.Default.UseGDIWhenDrawBorder)
                {   // Use Polyline with NOT_XOR_PEN form GDI
                    rect.X -= 2;
                    rect.Y -= 2;
                    rect.Width += 3;
                    rect.Height += 3;
                }
                else
                {   // Use ControlPaint.DrawReversibleFrame (GDI+)
                    rect.X -= 1;
                    rect.Y -= 1;
                    rect.Width += 3;
                    rect.Height += 3;
                }
#else
#if DEBUG
                rect.X -= left;
                rect.Y -= top;
                rect.Width += (left + right);
                rect.Height += (top + bot);
#endif
#endif
                DienLib.WinAPI.BlinkBorderBefore(rect);
                if (_refobj.InvokeRequired) _refobj.Invoke((MethodInvoker)delegate { DienLib.Reflector.SetProperty(_refobj, "Unit", value); });
                else DienLib.Reflector.SetProperty(_refobj, "Unit", value);
                DienLib.WinAPI.BlinkBorderAfter(_refobj);
            }
        }


        #region For UnitTest
#if DEBUG
        bool once = true;
        bool _isLabel;
        [System.Diagnostics.Conditional("DEBUG")]
        public void _DebugDrawBorder_UnitTextBox_ExpandPartial(Point p)
        {
            if (_isLabel) _isLabel = false; else _isLabel = true;
            switch (p.X)
            {
                case 0: a_TextBoxEdit.Invalidate(); break;
                case 1: a_PanelTextBoxState.Invalidate(); break;
                case 2: a_Splitter1.Panel1.Invalidate(); break;
                case 3: a_Splitter1.Panel2.Invalidate(); break;
                case 4: a_Splitter1.Invalidate(); break;
                case 5: a_LabelUnit.Invalidate(); break;
                case 6: a_PanelBorder.Invalidate(); break;
                case 7: ((Control)_refobj).Invalidate(); break;
                case 8: a_TextBoxEdit.Refresh(); break;
                case 9: a_Splitter1.Panel1.Refresh(); break;
            }
            if (once)
            {
                once = false;

                //PanelTextboxState : 50,25 , 300,150
                //a_PanelTextBoxState.Dock = DockStyle.None;
                //a_PanelTextBoxState.Location = new Point(3, 3);
                //a_PanelTextBoxState.Size = new Size(64, 21);
                //a_PanelTextBoxState.BackColor = Color.Violet;

                //TextBoxEdit : 50,25 , 200,100
                a_TextBoxEdit.Dock = DockStyle.None;
                a_TextBoxEdit.Multiline = true;
                a_TextBoxEdit.WordWrap = true;
                //a_TextBoxEdit.Location = new Point(50, 25);
                //a_TextBoxEdit.Size = new Size(200, 100);
                //a_TextBoxEdit.BackColor = Color.White;
                a_TextBoxEdit.Visible = false;
            }
        }

        [System.Diagnostics.Conditional("DEBUG")]
        public void _DebugDrawBorder_UnitTextBox_ExpandAll(Point p)
        {
            // Bung ra toan bo luon
            //UserControl : 10,10 , 910,300 : RED
            DienLib.Reflector.SetProperty<Point>(_refobj, "Location", new Point(10, 10));
            DienLib.Reflector.SetProperty<Size>(_refobj, "Size", new Size(910, 300));
            //Set Color RED

            //PanelBorder : 50,25 , 810,250
            a_PanelBorder.Dock = DockStyle.None;
            a_PanelBorder.Location = new Point(50, 25);
            a_PanelBorder.Size = new Size(810, 250);
            a_PanelBorder.BackColor = Color.Orange;

            //Splitter1 : 50,25 , 710,200
            a_Splitter1.Dock = DockStyle.None;
            a_Splitter1.Location = new Point(50, 25);
            a_Splitter1.Size = new Size(710, 200);
            a_Splitter1.BackColor = Color.Yellow;
            a_Splitter1.SplitterDistance = 400;
            a_Splitter1.SplitterWidth = 10;
            a_Splitter1.Panel1.BackColor = Color.Green;
            a_Splitter1.Panel2.BackColor = Color.Blue;

            //PanelTextboxState : 50,25 , 300,150
            a_PanelTextBoxState.Dock = DockStyle.None;
            a_PanelTextBoxState.Location = new Point(50, 25);
            a_PanelTextBoxState.Size = new Size(300, 150);
            a_PanelTextBoxState.BackColor = Color.Violet;

            //TextBoxEdit : 50,25 , 200,100
            a_TextBoxEdit.Dock = DockStyle.None;
            a_TextBoxEdit.Multiline = true;
            a_TextBoxEdit.WordWrap = true;
            a_TextBoxEdit.Location = new Point(50, 25);
            a_TextBoxEdit.Size = new Size(200, 100);
            a_TextBoxEdit.BackColor = Color.White;
            a_TextBoxEdit.Visible = false;

            //Label : 50,25 , 200,150
            a_LabelUnit.Dock = DockStyle.None;
            a_LabelUnit.Location = new Point(50, 25);
            a_LabelUnit.Size = new Size(200, 150);
            a_LabelUnit.BackColor = Color.Gray;
        }
#endif
        #endregion


        #region DISPOSE METHOD
        // Dispose() calls Dispose(true)
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // NOTE: Leave out the finalizer altogether if this class doesn't 
        // own unmanaged resources itself, but leave the other methods
        // exactly as they are. 
        ~UnitTextBox() 
        {
            // Finalizer calls Dispose(false)
            Dispose(false);
        }

        // The bulk of the clean-up code is implemented in Dispose(bool)
        protected virtual void Dispose(bool disposing)
        {
            if (disposing) 
            {
                // free managed resources, (detach event ?)
                if (this._refobj != null) this._refobj = null; // Khong keu this._refobj.Dispose vi Reference toi object do. Ngoai ra do pass reference nen this._refobj = null khong anh huong gi toi object goc
                if (this.a_LabelUnit != null) this.a_LabelUnit = null;
#if DEBUG
                if (this.a_PanelBorder != null) this.a_PanelBorder = null;
                if (this.a_PanelTextBoxState != null) this.a_PanelTextBoxState = null;
                if (this.a_Splitter1 != null) this.a_Splitter1 = null;
#endif
                if (this.a_TextBoxEdit != null) this.a_TextBoxEdit = null;
            }

            /* free native resources if there are any.
            if (nativeResource != IntPtr.Zero) 
            {
                Marshal.FreeHGlobal(nativeResource);
                nativeResource = IntPtr.Zero;
            }*/
        }
        #endregion
    }
}